﻿import MySecurity.*;
/**
* ¶ԳƼÓÃÜË㷨 XXTea
*/
class MySecurity.XXTea{
	public static var say:Function;
	
	/**
	* ¼ÓÃÜutf8
	* @param	str Ҫ¼ÓÃܵÄ×ִ®
	* @param	key ¼ÓÃÜÓõÄKey
	* @return	¼ÓÃܺóµÄ×ִ®
	*/
	public static function EncodeUTF8(str:String, key:String):String {
		if (str == "" || str ==undefined) {
			say("¼ÓÃÜÊý¾ÝΪ¿ա£");
			return "";
		}
		if(key == "" || key == undefined){
			say("ÃÜԿΪ¿ա£");
			return "";
		}
		var v:Array = str2long(str, true);
		var k:Array = str2long(key, false);
		
//trace("v:"+v);
//trace("k:"+k);
		
		var n:Number = v.length - 1;

		var z:Number = v[n], y:Number = v[0], delta:Number = 0x9E3779B9;
		var mx:Number, e:Number, q:Number = Math.floor(6 + 52 / (n + 1));
		var sum:Number = 0;
//trace(":: "+z+"|"+y+"|"+delta+"|"+mx+"|"+e+"|"+q+"|"+sum)
		while (q-- > 0) {
			sum=int32(sum);
			sum = sum + delta & 0xffffffff;
			e = sum >>> 2 & 3;
			var p=0;
//trace("::::: "+z+"|"+y+"|"+delta+"|"+mx+"|"+e+"|"+q+"|"+sum)
			while(p < n){
				y = v[p + 1];
				//trace(":::::: K = ["+k.length+"] ... "+(p & 3 ^ e) +" == "+k[p & 3 ^ e] + " | "+(k[p & 3 ^ e] ^ z));
				mx = int32(((z >> 5 & 0x07ffffff) ^ y << 2) + ((y >> 3 & 0x1fffffff) ^ z << 4)) ^ int32((sum ^ y) + (k[p & 3 ^ e] ^ z));
				z = v[p] = int32(v[p] + mx & 0xffffffff);
//trace(mx+" | "+z)
				p++;
			}
			y = v[0];
			mx = int32(((z >> 5 & 0x07ffffff) ^ y << 2) + ((y >> 3 & 0x1fffffff) ^ z << 4)) ^ int32((sum ^ y) + (k[p & 3 ^ e] ^ z));
			z = v[n] = int32(v[n] + mx & 0xffffffff);
		}

		return long2str(v, false);
	}
	/**
	* ¼ÓÃÜutf8
	* @param	str Ҫ½âÃܵÄ×ִ®
	* @param	key ½âÃÜÓõÄKey
	* @return	½âÃܺóµÄ×ִ®
	*/
	public static function DecodeUTF8(str:String, key:String):String {
		if (str == "" || str ==undefined) {
			say("½âÃÜÊý¾ÝΪ¿ա£");
			return "";
		}
		if(key == "" || key == undefined){
			say("ÃÜԿΪ¿ա£");
			return "";
		}
		var v:Array = str2long(str, false);
		var k:Array = str2long(key, false);
		
		
trace("v:"+v);
trace("k:"+k);
		
		
		var n:Number = v.length - 1;

		var z:Number = v[n - 1], y:Number= v[0], delta:Number = 0x9E3779B9;
		var mx:Number, e:Number, q:Number = Math.floor(6 + 52 / (n + 1));
		var sum:Number = q * delta & 0xffffffff;
		while (sum != 0) {
			e = sum >>> 2 & 3;
			var p:Number=n;
			while(p>0){
				z = v[p - 1];
				mx = int32(((z >> 5 & 0x07ffffff) ^ y << 2) + ((y >> 3 & 0x1fffffff) ^ z << 4)) ^ int32((sum ^ y) + (k[p & 3 ^ e] ^ z));
				y = v[p] = int32(v[p] - mx & 0xffffffff);
				p--;
			}
			z = v[n];
			mx = int32(((z >> 5 & 0x07ffffff) ^ y << 2) + ((y >> 3 & 0x1fffffff) ^ z << 4)) ^ int32((sum ^ y) + (k[p & 3 ^ e] ^ z));
			y = v[0] = int32(v[0] - mx & 0xffffffff);
			sum = int32(sum - delta & 0xffffffff);
		}
		trace(v);
		return long2str(v, true);
	}
	
	private static function int32(n:Number):Number {
		while (n >= 2147483648) n -= 4294967296;
		while (n <= -2147483649) n += 4294967296; 
		return n;
	}
	public static function EncodeUTF16(str:String,key:String):String{
		
		if (str == "" || str == undefined) {
			say("¼ÓÃÜÊý¾ÝΪ¿ա£");
			return "";
		}
		if(key == "" || key == undefined){
			say("ÃÜԿΪ¿ա£");
			return "";
		}
		var str2:String=Utf.utf16to8(str);
		return EncodeUTF8(str2,key);
	}
	public static function DecodeUTF16(str:String,key:String):String{
		if (str == "" || str ==undefined) {
			say("½âÃÜÊý¾ÝΪ¿ա£");
			return "";
		}
		if(key == "" || key == undefined){
			
			say("ÃÜԿΪ¿ա£");
			return "";
		}
		var str2:String=DecodeUTF8(str,key);
		return Utf.utf8to16(str2);
	}
	private static function long2str(v:Array, w:Boolean):String {
		var vl:Number = v.length;
		var sl:Number = v[vl - 1] & 0xffffffff;
		var i:Number=0;

//trace("["+w+"]sl = "+sl);
		
		while(i<vl){
			var n:Array=[v[i] & 0xff,v[i] >>> 8 & 0xff, v[i] >>> 16 & 0xff, v[i] >>> 24 & 0xff]
			v[i] = String.fromCharCode(n[0],n[1],n[2],n[3]);
///trace("n="+n+"["+v[i]+"]")
			i++;
		}
		if (w) {
			return v.join('').substring(0, sl);
		}
		else {
			return v.join('');
		}
	}
	
	private static function str2long(s:String, w:Boolean):Array {
		var len:Number = s.length;
		var v:Array = new Array();
		var i:Number=0;
		while(i<len){
			v.push(s.charCodeAt(i) | s.charCodeAt(i + 1) << 8 | s.charCodeAt(i + 2) << 16 | s.charCodeAt(i + 3) << 24);
			i += 4;
		}
		if (w) {
			v.push(len);
		}
		return v;
	}
}